/*
PhotoView, R.R. Nederhoed, r.r.nederhoed@gmail.com

Depends on jQuery

TODO: append image index to location bar, for bookmarkability
*/

function debug (msg) {
    $("#debugger").append(msg);
};

// HELPERS
Array.prototype.contains = function (element) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == element) { return true; }
    }
    return false;
};
Array.prototype.index = function (element) {
    // RRN 2007-12-27
    for (var i = 0; i < this.length; i++) {
        if (this[i] == element) { return i; }
    }
    // Throw exception?
    return null;
};

/* Generate a callback function for easy PhotoView creation 
    @param `images` required
    @param `position` optional
*/
function GetPhotoViewCallback (images, position) {
    var position = (position == null) ? 0 : position;
    return function () {
        // Create PhotoView instance
        pv = new PhotoView(images);
        // Bind button with PhotoView actions
        PhotoViewHookup(pv);
        // Show first photo
        pv.set_state(position);
    };
};

/* Link PhotoView instance to HTML */
function PhotoViewHookup(photoview) {
    // Up and down buttons
    $(".photo_down").click(function () {photoview.next();});
    $(".photo_up").click(function () {photoview.previous();});
    
    // Bind hover events for visual effects
    // TODO: hover via CSS?
    partial = function (target, url) {
        return function () { target.attr('src', url); }
    };
    ids = [".photo_down", ".photo_up"];
    for (i = 0; i < ids.length; i++) {
        buttons = $(ids[i]);
        for (j = 0; j < buttons.length; j++) {
            button = $(buttons[j]);
            init_url = button.attr('src');
            hover_url = $(ids[i] + "-hover:first").attr('src');
            $(button).hover(
                partial(button, hover_url),
                partial(button, init_url)
            );
        };
    };
    
    // Individual images
    partial = function (j) { return function () { photoview.set_state(j); } };
    for (var i = 0; i < photoview.images.length; i++) {
        // Creative solution :)
        photoview.images[i].click(partial(i));
    }
};

// PhotoView Namespace
function PhotoView (urls) {
    /* Public attributes */
    this.max = 5; // must be an odd number
    this.speed = 500; // msec
    
    /* Private attributes */
    this.position = 0;
    this.images = [];
    this.images_shown = [];
    // Image identification
    this.key = "photo_id_"; 
    
    /* Protected methods */
    // Focus (high-light)
    this.addFocus = function (position) {
        //$("#" + this.key + position).addClass("focus");
        this.images[position].addClass("focus");
    };
    this.removeFocus = function (position) {
        //$("#" + this.key + position).removeClass("focus");
        this.images[position].removeClass("focus");
    };
    // Larger version
    this.showBig = function (index) {
        // Show BIG image in center
        var url = this.images[index].attr("src");
        var image = '<img src="' + url + '" alt="" />';
        $("#photo_center").html(image);
    };
    // Animation
    this.showImage = function (image) {
        image.slideDown(this.speed);
    };
    this.hideImage = function (image) {
        image.slideUp(this.speed);
    };
    // Visibility Logic
    this.set_state = function (position) {
        // How many images should be shown ideally on each side
        if (position < 0 || position >= this.images.length) {
            return;
        };
        // Surrounding images
        if (this.images.length < this.max) {
            // All images should be visible: copy them
            show = this.images.slice();
        }
        else {
            show = [];
            show.push(this.images[position]);
            for (var i=1; i < this.max; i++) {
                if (position-i >= 0) {
                    show.unshift(this.images[position-i]);
                };
                if (position+i < this.images.length) {
                    show.push(this.images[position+i]);
                };
                if (show.length >= this.max) {
                    break;
                };
            };
        };
        
        for (i in this.images) {
            image = this.images[i];
            is_visible = this.images_shown.contains(image);
            be_shown = show.contains(image);
            if (is_visible && !(be_shown)) {
                this.hideImage(image);
            };
            if ((!is_visible) && be_shown) {
                this.showImage(image);
            };
        }
        // Adjust to new situation
        this.images_shown = show.slice();
        this.showBig(position);
        // Focus
        this.removeFocus(this.position);
        this.position = position;
        this.addFocus(position);
        // Numbers
        this.updateCounter();
    };
    // Imagery
    this.addImage = function (url) {
        // Assign ID
        var id = "" + this.key + this.images.length;
        // Generate HTML
        var template = '<img src="' + url + '" id="' + id + '" width="136" />';
        $("#photo_target_mini").before(template);
        // Hide
        $("#" + id).hide();
        // Index DOM element
        this.images[this.images.length] = $("#" + id);
    };
    /* Add an array of image urls */
    this.addImages = function(images) {
        for (i=0; i < images.length; i++) {
            this.addImage(images[i]);
        };
    };
    
    // Add images from parameter
    if (urls != null) {
        this.addImages(urls);
    };
};
// Public methods
PhotoView.prototype.next = function () {
    // Boundary
    if (this.position < this.images.length-1) {
        this.set_state(this.position+1);
    }
    else {
        this.set_state(0);
    };
}
PhotoView.prototype.previous = function () {
    // Boundary
    if (this.position > 0) {
        this.set_state(this.position-1);
    }
    else {
        this.set_state(this.images.length-1);
    };
}
PhotoView.prototype.updateCounter = function () {
    // Position: photo index
    $("#photo_position").html((1 + this.position) + " / " + this.images.length);
}
